package com.dave.admin.modular.boss.handler;

import cn.hutool.http.HttpException;
import com.dave.admin.common.exception.AssertionException;
import com.dave.admin.common.result.CommonResult;
import com.dave.admin.common.result.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * 全局错误处理
 *
 * 如果需要自定义全局错误可以注释掉这个
 * @author Dave
 */
@Order(2)
@RestControllerAdvice(basePackages = "com.dave")
public class BossExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 参数内容匹配规则校验处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult validationBodyException(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        if (result.hasErrors()) {
            List<ObjectError> errorList = result.getAllErrors();
            for (ObjectError error : errorList) {
                logger.info("参数请求错误：请求字段【{}】：请求值【{}】：错误提示【参数{}】", ((FieldError) error).getField(), (((FieldError) error).getRejectedValue()), error.getDefaultMessage());
                return CommonResult.failed(error.getDefaultMessage());
            }
        }
        return CommonResult.failed(ResultCode.VALIDATE_FAILED);
    }

    /**
     * 参数内容匹配规则校验处理
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public CommonResult handleValidationException(ConstraintViolationException e) {
        for (ConstraintViolation<?> s : e.getConstraintViolations()) {
            logger.info("参数请求错误 【" + s.getPropertyPath() + "】: 请求值【" + s.getInvalidValue() + "】:【" + s.getMessage() + "】");
        }
        return CommonResult.failed(ResultCode.VALIDATE_FAILED);
    }


    /**
     * 参数内容匹配规则校验处理
     */
    @ExceptionHandler(BindException.class)
    public CommonResult handleBindException(BindException e, HttpServletRequest httpServletRequest) {
        e.getFieldErrors().stream().forEach(x -> {
            logger.info("请求地址【" + httpServletRequest.getRequestURI() + "】：参数请求错误 【" + x.getField() + "】: 请求值【" + x.getRejectedValue() + "】:【" + x.getDefaultMessage() + "】");
        });
        logger.error(e.getMessage(),e);
        return CommonResult.failed(ResultCode.VALIDATE_FAILED);
    }


    /**
     * 请求参数找不到报错处理
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public CommonResult handleValidationException(MissingServletRequestParameterException e) {
        logger.info("参数请求错误【" + e.getMessage() + "】");
        return CommonResult.failed(ResultCode.VALIDATE_FAILED);
    }

    /**
     * 程序校验错误自定义抛出
     */
    @ExceptionHandler(AssertionException.class)
    public CommonResult handleAssertionException(AssertionException e) {
        logger.error("程序自定义检验业务【" + e.getMessage() + "】", e);
        return CommonResult.failed(e.getMessage());
    }


    /**
     * 程序校验错误自定义抛出
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public CommonResult handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest httpServletRequest) {
        logger.info("【方法:{}，{},支持{}方式请求】", httpServletRequest.getRequestURI(), e.getMessage(), e.getSupportedMethods());
        return CommonResult.failed("请求方式不正确");
    }

    /**
     * 网络连接错误
     */
    @ExceptionHandler(HttpException.class)
    public CommonResult handleHttpException(HttpException e) {
        logger.error(e.getMessage(), e);
        return CommonResult.failed(ResultCode.REMOTE_ERROR);
    }

    /**
     * 没有权限的异常不要吃了：抛出去 外层有一个ExceptionTranslationFilter 会处理这个异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public void handlerAccessDeniedException(AccessDeniedException e) {
        throw e;
    }


    /**
     * Exception抛出
     */
    @ExceptionHandler(Exception.class)
    public CommonResult handleException(Exception e) {
        logger.error("未知错误【" + e.getMessage() + "】", e);
        return CommonResult.failed();
    }
}
